home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1993 July / InfoMagic USENET CD-ROM July 1993.ISO / sources / misc / volume27 / psf3 / part07 < prev    next >
Encoding:
Text File  |  1992-01-20  |  44.3 KB  |  1,573 lines

  1. Newsgroups: comp.sources.misc
  2. From: tony@ajfcal.cuc.ab.ca (Tony Field)
  3. Subject:  v27i098:  psf3 - Postscript print filter system, v3, Part07/09
  4. Message-ID: <1992Jan21.013457.11741@sparky.imd.sterling.com>
  5. X-Md4-Signature: 54b321998944723eb6e89faa2c87bfa4
  6. Date: Tue, 21 Jan 1992 01:34:57 GMT
  7. Approved: kent@sparky.imd.sterling.com
  8.  
  9. Submitted-by: tony@ajfcal.cuc.ab.ca (Tony Field)
  10. Posting-number: Volume 27, Issue 98
  11. Archive-name: psf3/part07
  12. Environment: ISC, SUNOS, SYSVR3, DOS
  13. Supersedes: psf2: Volume 12, Issue 4-9
  14.  
  15. #! /bin/sh
  16. # This is a shell archive.  Remove anything before this line, then unpack
  17. # it by saving it into a file and typing "sh file".  To overwrite existing
  18. # files, type "sh file -c".  You can also feed this as standard input via
  19. # unshar, or by typing "sh <file", e.g..  If this archive is complete, you
  20. # will see the following message at the end:
  21. #        "End of archive 7 (of 9)."
  22. # Contents:  Install.lpd psfbanner.c psfdoub.c
  23. # Wrapped by ajf@trifid on Sat Jan 18 22:55:50 1992
  24. PATH=/bin:/usr/bin:/usr/ucb ; export PATH
  25. if test -f 'Install.lpd' -a "${1}" != "-c" ; then 
  26.   echo shar: Will not clobber existing file \"'Install.lpd'\"
  27. else
  28. echo shar: Extracting \"'Install.lpd'\" \(11083 characters\)
  29. sed "s/^X//" >'Install.lpd' <<'END_OF_FILE'
  30. X                PSF AND LPR/LPD
  31. X
  32. X    1.    If the psf systems has been successfully compiled and
  33. X        installed with the sequence of commands (see Install.unix):
  34. X
  35. X        make all
  36. X        make printer
  37. X        make scripts
  38. X        make install
  39. X
  40. X    filters and a suitable /etc/printcap file should be constructed
  41. X    as outlined below.
  42. X
  43. X    The "make install" process set links to psflpd for a few page
  44. X    layouts. Since the the sample set of links may not be
  45. X    appropriate, the links may be deleted and/or a new set of links
  46. X    added. Read the instructions below to set options for various
  47. X    links to psflpd.
  48. X
  49. X    A sample printcap entry using the various filters was created
  50. X    during the "make script" process and placed in file "printcap".
  51. X    Use this document and the sample printcap file as a guide to
  52. X    construct a suitable printcap file and construction of other
  53. X    filters for your site.
  54. X
  55. X    File printcap.NET is a sample printcap for network hosts that
  56. X    wish to access a server host.
  57. X
  58. X    In any case, psf may always be used at the command line since
  59. X    psflpd and friends do not reprocess any text that is already
  60. X    in postscript format:
  61. X
  62. X        e.g.    psf -4x this.txt | lpr
  63. X    
  64. X
  65. X   2.    FILTER NAMING, PSFPRINT.DEF
  66. X  
  67. X    The programme "psflpd" is the binary used for print filtering by
  68. X    lpd.  Lpd does not pass sufficient parameters to print filters to
  69. X    allow selection of various options supported by psflpd. To get
  70. X    around this problem, links to psflpd can be constructed which
  71. X    invoke different print options.  The desired print options
  72. X    for each link name are manually edited into psfprint.def.
  73. X    These lines must be at  the beginning of the file.  (A full
  74. X    example of a psfprint.def file with print options is given
  75. X    at the end of this document.)
  76. X
  77. X    For example, if a link were made:
  78. X
  79. X        ln psflpd p2up
  80. X    
  81. X    then, if p2up were executed as a print filter, it would
  82. X    print the page  2-up in portrait layout.  The associated
  83. X    printcap entry would use p2up as the print "if" or "of"
  84. X    filter:
  85. X        if=/usr/local/lib/psf/p2up
  86. X    
  87. X    The entry in psfprint.def defining the options for use
  88. X    with the p2up filter would look like:
  89. X    
  90. X        *psflpd p2up -2
  91. X    
  92. X    The general format of the entries placed in psfprint.def is:
  93. X    
  94. X        *psflpd <linkname> <opt> <opt> ... #comment
  95. X    
  96. X    where  *psflpd     identifies the line for psflpd option selection.
  97. X           <linkname>  the name of the link to psflpd
  98. X           <opt>       any psf(1) option  (except that quoted
  99. X                      options are not allowed. e.g. -H "text line"
  100. X                      is not permitted)
  101. X    
  102. X    A selection of (hopefully) useful link names and option entries
  103. X    was created by "make printer" and placed in psfprint.def.  The
  104. X    associated links to lpd were created by "make install"
  105. X    
  106. X    Edit psfprint.def, create new links to psflpd, and modify the
  107. X    print cap entries for different print options.  For example,
  108. X    If you have a "General Accounting" package that requires special
  109. X    print formatting, a link to psflpd could be set up with the
  110. X    exact options neccesary for the print layout.  Typically,
  111. X    such reports print 66 lines on a page, 6 of which are used
  112. X    to emulate a "skip to head of forms".  A suitable set of
  113. X    print options for such a report would be:
  114. X    
  115. X        *psflpd paccount -c132 -l60 -R2 -r6 -w
  116. X
  117. X    This would cause the printout to be 132 columns by 60 lines
  118. X    in landscape layout. Two lines would be    removed from the
  119. X    beginning of the file, and 6 lines between pages.
  120. X
  121. X
  122. X   3.    CREATION OF /ETC/PRINTCAP ENTRIES
  123. X   
  124. X    A sample file "printcap" was created during the install. Use the
  125. X    sample file and/or commentary below to construct a printcap
  126. X    entry for your system. ( Examine printcap.NET to set up printcap
  127. X    entries for network hosts needing access to a print server. )
  128. X
  129. X    The general strategy is to create a series of printer names that
  130. X    are representative of options desired. For example, the printer
  131. X    name "2up" suggest that the pages will be printed 2-up. 
  132. X    
  133. X    For each printer defined, set the name of the input (if=) or
  134. X    output (of=) filter to the name of a link to psflpd.
  135. X
  136. X    For each link created, edit psfprint.def to set the print
  137. X    options associated with the link name.
  138. X
  139. X    The various aliases of psflpd created by links should be used as
  140. X    output (of=) filters.  Ensure that the form feed character is
  141. X    suppressed with the :sf printcap (or possibly use the ff=\0
  142. X    printcap).
  143. X
  144. X       # sample /etc/printcap entry for psflpd (or links)
  145. X       # lp     uses psflpd     = normal page print, 12 point, portrait
  146. X       # 2up    uses psl2up     = print 2 up on a page, landscape
  147. X       # acct   uses paccount   = 132x60 page on letter paper
  148. X       
  149. X       lp|standard postscript:\
  150. X        :lp=/dev/lp:sd=/usr/spool/lpd/lp:\
  151. X        :lf=/usr/adm/lpd-errs: \
  152. X        :if=/usr/lib/lpdfilters/psf/psflpd:sh:sf
  153. X
  154. X       2up|2up postscript:\
  155. X        :lp=/dev/lp:sd=/usr/spool/lpd/lp:\
  156. X        :lf=/usr/adm/lpd-errs: \
  157. X        :if=/usr/lib/lpdfilters/psf/p2up:sh:sf
  158. X
  159. X       acct|gen accounting:\
  160. X        :lp=/dev/lp:sd=/usr/spool/lpd/lp:\
  161. X        :lf=/usr/adm/lpd-errs: \
  162. X        :if=/usr/lib/lpdfilters/psf/paccount:sh:sf
  163. X
  164. X    No entry for "psflpd" is needed in psfprint.def. However,
  165. X    they should be made for "p2up" and "paccount" and look like:
  166. X    
  167. X        *psflpd p2up -2
  168. X        *psflpd paccount -c132 -l60 -R2 -r6 -w
  169. X
  170. X    Links for p2up and paccount should be made:
  171. X    
  172. X        ln psflpd ps2up
  173. X        ln psflpd paccount
  174. X
  175. X    4.  The example printcap entries above use the input (if=) filter 
  176. X    and suppresses the banner page. If you wish to print the banner
  177. X    page, remove the ":sh" and use output (of=) filters.
  178. X
  179. X    The output (of=) filters also process the banner page generated
  180. X    by lpd. The input (if=) filters do not. (The output (of=)
  181. X    filters may be more efficient: I think that the of= filter is
  182. X    executed once for a group of files, while the input (if=) filer
  183. X    is invoked for every file being printed in a group.)
  184. X
  185. X    If banner printing IS desired, use psflpd and friends as an "of="
  186. X    filter. Beware that the banner page will probably be truncated if
  187. X    printing is in portrat layout.
  188. X
  189. X    If banner printing is NOT desired, use psflpd and friends as an
  190. X    "if=" or "of=" filter and suppress banners with :sh.
  191. X
  192. X    If you are not happy with the banner page layout printed by your
  193. X    postscript printer, then the only suggestion I have is to modify
  194. X    the sources for lpd!
  195. X
  196. X
  197. X   5.    PRINTING POSTSCRIPT SOURCE
  198. X   
  199. X    If Postscript code must be printed, filter the source manually
  200. X    with psf - otherwise the psflpd will pass the code to the
  201. X    printer for execution:
  202. X
  203. X        psf mycode.ps | lp
  204. X
  205. X    As an alternative, a link to psflpd could be set up such that
  206. X    the associated print options use the "-z" switch to force the
  207. X    printing of the postscript code. A sample printer printcap entry
  208. X    (post) to allow printing of postscript source was set up during
  209. X    the install process.  Usage:
  210. X    
  211. X        lpr -Ppost mycode.ps
  212. X
  213. X
  214. X   6.    MULTIPLE PRINTER SUPPORT
  215. X
  216. X          If these filters are to control multiple different postscript
  217. X    printers on the same system, then separate editions of psflpd
  218. X    and friends should be compiled an placed in different directores:
  219. X    one for each different printer.  For example, if you have a
  220. X    Nec and and Apple postscript printer, place the binaries and
  221. X    psfprint.def files in a directory that reflects each printer:
  222. X    
  223. X        /usr/lib/lpdfilters/nec/*
  224. X       -and-
  225. X           /usr/lib/lpdfilters/apple/*
  226. X
  227. X    Modify the Makefile to compile for each set of directories.
  228. X    
  229. X    Rename each version of psf (for interactive use) to an
  230. X    appropriate unique name (psfn and psfa). An alternative is ask
  231. X    the user to use the "-u alt.def" option of psf when selecting
  232. X    different printers.
  233. X
  234. X    The Makefile allows you to change target directories and binary
  235. X    programme names. Be careful when you "make install" after
  236. X    major changes (use "make -n installbsd" to check things out).
  237. X
  238. X
  239. X    7.  HOW DOES A USER ACCESS THE APPROPRIATE PRINTER?
  240. X   
  241. X    Any of the printers defined in /etc/printcap may be selected
  242. X    depending upon the desired page layout! General printing to the
  243. X    default printer "lp" would be done with:
  244. X
  245. X        lpr my.file
  246. X    
  247. X    Two up printing would be done with:
  248. X    
  249. X        lpr -P2up my.file
  250. X    
  251. X    As another example, an MSDOS user with Wollongong tcp/ip might
  252. X    print a file from dos with:
  253. X
  254. X        lpr -P 2up source.c    <-sends for 2up printing
  255. X       - or -
  256. X        lprint            <- set up Wollongong printers
  257. X        lprq lpt1 ajfcal:2up    <- set lpt1 = up printing
  258. X        lprq lpt3 ajfcal:lp    <- set lpt3 = standard printing
  259. X
  260. X        copy source.c lpt1    <- prints 2up on a page
  261. X        copy other.txt lpt3    <- prints 1up on a page
  262. X
  263. X        psf source.c > lpt1    <- since psf already formats the 
  264. X                       text on dos, sending it to
  265. X                       any printer on ajfcal simply
  266. X                       passes the already done
  267. X                       postscript to the printer
  268. X                       without additional
  269. X                       processing.
  270. X
  271. X    With Wollongong tcp/ips on dos, the pc can be readily set up
  272. X    as a print server to serve other dos and/or unix systems.
  273. X    However, psf cannot be used on the dos server as a filter
  274. X    because the dos-side print server does not allow additional
  275. X    filtering. Thus the client must first format with psf before
  276. X    sending to the dos print server:
  277. X
  278. X        psf -4xh source.c | lpr -Pdoslpr
  279. X
  280. X
  281. X    8.    PRINTING PROBLEMS
  282. X   
  283. X        The most common problem associated with lpd and postscript
  284. X    printers is the lack of printed output: files appear to be
  285. X    printing, however the printer times out and nothing is actually
  286. X    printed. Generally, this is caused by an invalid set of
  287. X    /etc/printcap options that allow lpd to send some characters to
  288. X    the printer without having those characters encapsulated in
  289. X    postscript.
  290. X
  291. X    Lpd may send banners and/or formfeed characters to the printer
  292. X    without proper filtration.
  293. X
  294. X    If banner pages are desired, then the psflpd filter must be used
  295. X    with the of= printcap since only the of= filters process the
  296. X    banners. If banner pages are not desired, then disable banners
  297. X    with the :sh printcap.
  298. X
  299. X    Disable unfiltered form-feeds with the :sf printcap or
  300. X    possibly set :ff=\0.
  301. X
  302. X    Different editions of lpd may (in rare circumstances) assign
  303. X    nonstandard meanings to various printcaps. This may cause
  304. X    unexpected printer action.
  305. X
  306. X    Since it is difficult to properly process lpd-generated banner
  307. X    pages, the recommended process is to suppress banner printing
  308. X    with the :sh printcap.
  309. X
  310. X
  311. X    9.  EXAMPLE OF A PSFPRINT.DEF FILE FOR USE WITH LPD
  312. X    
  313. X    # options for links to psflpd.
  314. X    #       link  options        comments
  315. X    #       ----  ----------------  -----------------------------
  316. X    *psflpd    p2up -2            # 2-up printing, default landscape
  317. X    *psflpd    p4up -4x        # 4-up printing, default portrait
  318. X    *psflpd    p132x60 -c132 -l60 -w    # 132 columns, 60 lines, landscape
  319. X    *psflpd psource -2xn        # source listings, 2-up, portrait
  320. X    *psflpd post -z2xn        # postscript source listings, 2-up
  321. X    *psflpd plegal -g legal        # standard print, legal paper
  322. X    *psflpd pspread -g legal -p 8 -w # spreadsheets: legal,8pt,landscape
  323. X    #
  324. X    # printer definition for psf and friends
  325. X    #
  326. X    *printer
  327. X    Sample Postscript Printer
  328. X    *paper 2
  329. X    Letter
  330. X    statusdict begin lettertray end
  331. X      612   792    18    15   593   777
  332. X    Legal
  333. X    statusdict begin legaltray end
  334. X      612  1008    18    15   593   993
  335. X    *order 1
  336. X    Normal
  337. X    *fonts 4
  338. X    Courier
  339. X    Helvetica
  340. X    Times-Roman
  341. X    ZapfChancery-MediumItalic
  342. X    *slots 2
  343. X    statusdict begin 1 setpapertray end
  344. X    statusdict begin 2 setpapertray end
  345. X    *eof
  346. X-----------------------
  347. XTony Field
  348. X(tony@ajfcal.cuc.ab.ca)
  349. END_OF_FILE
  350. if test 11083 -ne `wc -c <'Install.lpd'`; then
  351.     echo shar: \"'Install.lpd'\" unpacked with wrong size!
  352. fi
  353. # end of 'Install.lpd'
  354. fi
  355. if test -f 'psfbanner.c' -a "${1}" != "-c" ; then 
  356.   echo shar: Will not clobber existing file \"'psfbanner.c'\"
  357. else
  358. echo shar: Extracting \"'psfbanner.c'\" \(12737 characters\)
  359. sed "s/^X//" >'psfbanner.c' <<'END_OF_FILE'
  360. X/* ta=4 */
  361. X/****************************************************************************
  362. X*                p s f b a n n e r . c                                        *
  363. X*                                                                            *
  364. X*    Print a banner page on a postscript printer                                *
  365. X*                                                                            *
  366. X*    The generated print stream is NOT minimally conforming as per Red Book.    *
  367. X*                                                                            *
  368. X*    Tony Field.       tony@ajfcal.cuc.ab.ca                                    *
  369. X****************************************************************************/
  370. X
  371. X/*
  372. X * $Id: psfbanner.c,v 3.2 1992/01/19 05:50:33 ajf Exp ajf $
  373. X *
  374. X*/
  375. X
  376. X#include <stdio.h>
  377. X#include <string.h>
  378. X#include "ctp.h"
  379. X#include "psf.h"
  380. X#include "patchlevel.h"
  381. X
  382. X/* modifiy the following font selections if language changes
  383. X   are needed in psfprint.def. Also enable the language translation
  384. X   code at line 257  (   if (need_xlate)  )
  385. X*/
  386. X
  387. X#define FONT1 "/Helvetica-BoldOblique findfont %d scalefont setfont\n"
  388. X#define FONT2 "/Helvetica-Bold findfont %d scalefont setfont\n"
  389. X#define FONT3 "/Courier findfont %d scalefont setfont\n"
  390. X#define FONT4 "/Helvetica-Bold findfont %d scalefont setfont\n"
  391. X
  392. X/*    setup paper dimensions                                    */
  393. X
  394. Xtypedef struct                     /*    measurement in point                    */
  395. X{    char    paper_name[60];        /*    name of paper size (for command line)    */
  396. X    char    paper_tray[200];    /*    postscript operator to select this tray    */
  397. X    int        width;                /*    portrait point width of paper            */
  398. X    int        height;                /*    portrait point height of paper            */
  399. X    int        lx, ly, ux, uy;
  400. X} measure;
  401. X
  402. Xmeasure    *p;        /*    working set of parameters  (points to something below)     */
  403. X
  404. X                /*    standard paper sizes in portrait layout.                 */
  405. X
  406. Xmeasure    page_types[NPAGE] =
  407. X{            {     "letter",
  408. X                "statusdict begin lettertray end",
  409. X                  612,   792,    18,    15,   593,   777
  410. X            },
  411. X            {     "legal",
  412. X                "statusdict begin legaltray end",
  413. X                  612,  1008,    18,    15,   593,   993
  414. X            },
  415. X            {    "a4",
  416. X                "statusdict begin a4tray end",
  417. X                  595,   842,    18,    15,   578,   827
  418. X            },
  419. X            {    "b5",
  420. X                "statusdict begin b5tray end",
  421. X                  516,   729,    18,    15,   497,   712
  422. X            },
  423. X            {    "",            /* end of paper list */
  424. X                "",
  425. X                 0, 0,  0,  0, 0, 0
  426. X            }
  427. X};
  428. X
  429. Xchar    slots[NSLOTS][200] = 
  430. X{            "statusdict begin 1 setpapertray end",
  431. X            "statusdict begin 2 setpapertray end",
  432. X            "", "", "", ""
  433. X} ;
  434. Xint        nslots = 2;
  435. X
  436. Xint    X_INDENT    = 30;        /*    points                        */
  437. Xint Y_INDENT    = 30;
  438. Xint    BIG_POINT    = 60;        /* changes to point size automatically scale    */
  439. Xint MED_POINT    = 35;        /* the printout.                                */
  440. Xint    SMALL_POINT    = 15;
  441. Xint    UX, UY, DX, DY, MAX_X, MAX_Y;
  442. X
  443. X/*    The following arguments are received in the command line
  444. X    argv[9] and argv[10] may be page size and paper tray specifications.
  445. X    these could be:
  446. X    
  447. X            -b n    = select paper bin n
  448. X            -g size = selelct paper tray (letter, b5, etc)
  449. X*/
  450. X
  451. X#define    Userid        argv[1]
  452. X#define    Name        argv[2]
  453. X#define    Requestid    argv[3]
  454. X#define    Printer        argv[4]
  455. X#define    Options        argv[5]
  456. X#define    Date        argv[6]
  457. X#define    Machineid    argv[7]
  458. X#define    Title        argv[8]
  459. X
  460. Xchar    *defref = NULL;
  461. X
  462. XFILE    *outfp;
  463. Xunsigned char    xlate[256];            /*    translation vector     */
  464. Xint        need_xlate = 0;                /*    no default xlate    */
  465. XFILE    *pdef;
  466. Xvoid trim();
  467. X
  468. Xmain (argc, argv)
  469. Xint        argc;
  470. Xchar    *argv[];
  471. X{    int        x, y, c, i, set_paper_tray, set_paper_bin, number, j;
  472. X    char    line[200];
  473. X
  474. X    if (argc < 8)
  475. X        usage ();
  476. X
  477. X    for (i = 0;  i < 256;  i++)
  478. X        xlate[i] = i;
  479. X    
  480. X    outfp = stdout;
  481. X    pdef = NULL;
  482. X
  483. X    /* get user specified def file with -u */
  484. X
  485. X    for (i = 0;  i < argc;  i++)
  486. X    {    if (strncmp (argv[i], "-u", 2) == 0)
  487. X        {    if (strlen (argv[i]) > 2)
  488. X                defref = argv[i] + 2;
  489. X            else
  490. X                defref = argv[i+1];
  491. X            break;
  492. X        }
  493. X    }
  494. X    if (i >= argc)
  495. X        defref = PDEF;
  496. X
  497. X    if ((pdef = fopen (defref, "r")) != NULL)
  498. X    {    char    line_type[200];
  499. X
  500. X        while (fgets (line, 200, pdef))
  501. X        {    if (strncmp (line, "*printer", 8) == 0)
  502. X                break;
  503. X        }
  504. X        nslots = 0;
  505. X        fgets (line, 200, pdef);        /*    skip printer name     */
  506. X
  507. X        while (fgets (line, 200, pdef))
  508. X        {    trim (line);
  509. X            sscanf (line, "%s%d", line_type, &number);
  510. X
  511. X            if (strcmp (line_type, "*paper") == 0)
  512. X            {    for (i = j = 0;  i < number;  i++)
  513. X                {    if (i >= NPAGE - 1)
  514. X                    {    fgets (line, 200, pdef);
  515. X                        fgets (line, 200, pdef);
  516. X                        fgets (line, 200, pdef);
  517. X                        continue;
  518. X                    }
  519. X                    if (fgets (line, 200, pdef) == NULL)
  520. X                        bad_file();
  521. X                    line[59] = 0;
  522. X                    trim (line);
  523. X                    strcpy (page_types[i].paper_name, line);
  524. X                    if (fgets (line, 99, pdef) == NULL)
  525. X                        bad_file();
  526. X                    line[99] = 0;
  527. X                    trim (line);
  528. X                    strcpy (page_types[i].paper_tray, line);
  529. X                    if (fgets (line, 100, pdef) == NULL)
  530. X                        bad_file();
  531. X                    trim (line);
  532. X                    sscanf (line, "%d%d%d%d%d%d",
  533. X                        &page_types[i].width, &page_types[i].height,
  534. X                        &page_types[i].lx,    &page_types[i].ly,
  535. X                        &page_types[i].ux,    &page_types[i].uy);
  536. X                    j = i;
  537. X                }
  538. X                page_types[j+1].paper_name[0] = '\0';
  539. X            }
  540. X
  541. X            else if (strcmp (line_type, "*slots") == 0)
  542. X            {
  543. X                for (j = 0;  j < NSLOTS;  j++)
  544. X                    slots[j][0] = 0;
  545. X                for (i = j = 0;  i < number;  i++)
  546. X                {    if (fgets (line, 200, pdef) == NULL)
  547. X                        bad_file();
  548. X                    if (i >= NSLOTS)
  549. X                        continue;
  550. X                    line[99] = 0;
  551. X                    trim (line);
  552. X                    strcpy (slots[i], line);
  553. X                    j = i;
  554. X                }
  555. X                nslots = j + 1;
  556. X            }
  557. X
  558. X            else if (strcmp (line_type, "*eof") == 0)
  559. X                break;
  560. X        }
  561. X    }
  562. X
  563. X    MAX_X = page_types[0].width;
  564. X    MAX_Y = page_types[0].height;
  565. X    set_paper_bin = 0;
  566. X    set_paper_tray = -1;
  567. X    
  568. X    for (i = 9;  i < argc;  i++)
  569. X    {    if (argv[i][0] != '-')
  570. X            continue;
  571. X        c = argv[i][1];
  572. X        switch (c)
  573. X        {
  574. X        case 'b':
  575. X            if ((set_paper_bin = atoi (argv[i+1])) > nslots)
  576. X            {    fprintf (stderr, "paper bin greater than %d\n", nslots);
  577. X                exit (1);
  578. X            }
  579. X            i++;
  580. X            break;
  581. X
  582. X        case 'g':
  583. X            for (set_paper_tray = 0;  page_types[set_paper_tray].paper_name[0];  set_paper_tray++)
  584. X            {    if (compare (argv[i+1], page_types[set_paper_tray].paper_name) == 0)
  585. X                {    MAX_X = page_types[set_paper_tray].width;
  586. X                    MAX_Y = page_types[set_paper_tray].height;
  587. X                    break;
  588. X                }
  589. X            }
  590. X            if (page_types[set_paper_tray].paper_name[0] == '\0')
  591. X            {    fprintf (stderr, "Invalid paper size\n");
  592. X                exit (1);
  593. X            }
  594. X            i++;
  595. X            break;
  596. X
  597. X        case 'u':            /* already processed */
  598. X            break;
  599. X
  600. X        default: ;
  601. X        }
  602. X    }
  603. X
  604. X    UX    =    X_INDENT;
  605. X    UY    =    (MAX_Y - Y_INDENT);
  606. X    DX    =    (MAX_X - 2 * X_INDENT);
  607. X    DY    =    (BIG_POINT * 3);
  608. X
  609. X    /*    center text used for userid and job title print  */
  610. X    
  611. X    send ("%!\n");
  612. X    send ("/ctext {     % center text:   string x y dx\n");
  613. X    send ("   2 div\n");
  614. X    send ("   /Dx exch def\n");
  615. X    send ("   /Yv exch def\n");
  616. X    send ("   /Xv exch def\n");
  617. X    send ("   dup stringwidth pop\n");
  618. X    send ("   2 div\n");
  619. X    send ("   Dx exch sub\n");
  620. X    send ("   Xv add\n");
  621. X    send ("   Yv moveto\n");
  622. X    send ("   show\n");
  623. X    send ("} def\n");
  624. X    replacement_fonts();                /*    get font translations */
  625. X    send ("%%EndProlog\n");
  626. X
  627. X    /*    Uncomment the following code if languange translation is
  628. X        needed for the following parameters
  629. X    */
  630. X/*
  631. X    if (need_xlate)
  632. X    {    xlate_string (Userid);
  633. X        xlate_string (Name);
  634. X        xlate_string (Requestid);
  635. X        xlate_string (Printer);
  636. X        xlate_string (Options);
  637. X        xlate_string (Date);
  638. X        xlate_string (Machineid);
  639. X        xlate_string (Title);
  640. X    }
  641. X*/
  642. X    send ("%%Page: ? 1\n");
  643. X    if (set_paper_bin)
  644. X        printf ("%s\n", slots[set_paper_bin-1]);
  645. X
  646. X    if (set_paper_tray >= 0)
  647. X        printf ("%s\n", page_types[set_paper_tray].paper_tray);
  648. X        
  649. X    send ("/pg save def\n");
  650. X
  651. X    /*    draw a box for the userid */
  652. X    
  653. X    printf ("newpath\n");
  654. X    printf ("%d %d moveto\n", UX,UY);
  655. X    printf ("%d %d rlineto\n", DX, 0);
  656. X    printf ("%d %d rlineto\n", 0, -DY);
  657. X    printf ("%d %d rlineto\n", -DX, 0);
  658. X    printf ("closepath\n");
  659. X    printf ("4 setlinewidth\n");
  660. X    printf ("stroke\n");
  661. X
  662. X    /*    center the userid and the job title */
  663. X    
  664. X    y = UY - DY / 2 - BIG_POINT / 2;
  665. X    printf (FONT1, BIG_POINT);
  666. X    printf ("(%s) %d %d %d ctext\n", Userid, X_INDENT, y, DX);
  667. X
  668. X    y = UY - (DY + MED_POINT * 3);
  669. X    printf (FONT2, MED_POINT);
  670. X    printf ("(%s) %d %d %d ctext\n", Title, X_INDENT, y, DX);
  671. X
  672. X    /*    print other banner page parameters */
  673. X    
  674. X    x = X_INDENT;
  675. X    y -= (MED_POINT * 2);
  676. X    printf ("%d %d moveto\n", x,y);    
  677. X    sendnormal ("User:       ");
  678. X    sendbold (Name);
  679. X
  680. X    y -= SMALL_POINT + (SMALL_POINT / 2);
  681. X    printf ("%d %d moveto\n", x,y);    
  682. X    sendnormal ("Request ID: ");
  683. X    sendbold (Requestid);
  684. X    
  685. X    y -= SMALL_POINT + (SMALL_POINT / 2);
  686. X    printf ("%d %d moveto\n", x,y);    
  687. X    sendnormal ("Printer ID: ");
  688. X    sendbold (Printer);
  689. X    
  690. X    y -= SMALL_POINT + (SMALL_POINT / 2);
  691. X    printf ("%d %d moveto\n", x,y);    
  692. X    sendnormal ("Options:    ");
  693. X    sendbold (Options);
  694. X    
  695. X    y -= SMALL_POINT + (SMALL_POINT / 2);
  696. X    printf ("%d %d moveto\n", x,y);    
  697. X    sendnormal ("Date:       ");
  698. X    sendbold (Date);
  699. X    
  700. X    y -= SMALL_POINT + (SMALL_POINT / 2);
  701. X    printf ("%d %d moveto\n", x,y);    
  702. X    sendnormal ("Machine:    ");
  703. X    sendbold (Machineid);
  704. X
  705. X    send ("showpage pg restore\n");
  706. X    send ("%%Trailer\n");    
  707. X    exit (0);
  708. X}
  709. X
  710. X
  711. X/****************************************************************************
  712. X*    send font selection information and text.                                *
  713. X****************************************************************************/
  714. X
  715. Xsend (s)
  716. Xchar    *s;
  717. X{
  718. X    while (*s)
  719. X        fputc (*s++, outfp);
  720. X}
  721. X
  722. Xsendnormal (s)
  723. Xchar     *s;
  724. X{
  725. X    printf (FONT3, SMALL_POINT);
  726. X    send ("(");
  727. X    send (s);
  728. X    send (")show\n");
  729. X}
  730. X
  731. Xsendbold (s)
  732. Xchar     *s;
  733. X{
  734. X    printf (FONT4, SMALL_POINT);
  735. X    send ("(");
  736. X    send (s);
  737. X    send (")show\n");
  738. X}
  739. X
  740. X/****************************************************************************
  741. X*    trim ()                                                                    *
  742. X*    trucate garbage                                                            *
  743. X****************************************************************************/
  744. X
  745. Xvoid trim (s)                    /*    trim trailing blanks  and \n */
  746. Xchar    *s;
  747. X{    int many;
  748. X
  749. X    for (many = strlen (s) - 1;  many >= 0;  many--)
  750. X    {    if (isgraph (s[many]))
  751. X            break;
  752. X        else
  753. X            s[many] = '\0';
  754. X    }
  755. X}
  756. X
  757. X/****************************************************************************
  758. X*    bad_file()                                                                *
  759. X****************************************************************************/
  760. X
  761. Xbad_file()
  762. X{
  763. X    fprintf (stderr, "Bad %s file\n", defref);
  764. X    exit (1);
  765. X}
  766. X
  767. X/****************************************************************************
  768. X*    compare ()                                                                *
  769. X*    partial compare of two strings.                                            *
  770. X****************************************************************************/
  771. X
  772. Xcompare (a,b)
  773. Xchar    *a, *b;
  774. X{    int    aa, bb;
  775. X
  776. X    while (*a  &&  *b)
  777. X    {    aa = *a++;
  778. X        bb = *b++;
  779. X        if (UCCHAR (aa)  !=  UCCHAR (bb))
  780. X            return (aa - bb);
  781. X    }
  782. X    return (0);
  783. X}
  784. X
  785. X
  786. X/****************************************************************************
  787. X*    replacement_fonts()                                                        *
  788. X*    read the text translation strings only.                                    *
  789. X****************************************************************************/
  790. X
  791. Xreplacement_fonts ()
  792. X{    int        found, xold, xnew;
  793. X    char    line[201];
  794. X    char    *x;
  795. X
  796. X    if (pdef == NULL)
  797. X        return;
  798. X    found = 0;
  799. X    while (fgets (line, 200, pdef))        /*    skip printer name     */
  800. X    {    if (strncmp (line, "%%PsfStart", 10) == 0)
  801. X        {    found = 1;
  802. X            break;
  803. X        }
  804. X    }
  805. X    if (found)
  806. X    {    while (fgets (line, 200, pdef))            /*    read fonts, translate */
  807. X        {    if (strncmp (line, "%%PsfEnd", 8) == 0)
  808. X                break;
  809. X            if (strncmp (line, "%%translate",  11) == 0)
  810. X            {    x = strtok (line + 11, " ");
  811. X                do
  812. X                {    xold = otoi (x) % 256;
  813. X                    xnew = otoi (x+4) % 256;
  814. X                    xlate[xold] = xnew;
  815. X                } while (x = strtok (NULL, " "));
  816. X                need_xlate = 1;
  817. X            }
  818. X        }
  819. X        fclose (pdef);
  820. X        pdef = NULL;
  821. X    }
  822. X    else
  823. X    {    fclose (pdef);
  824. X        pdef = NULL;
  825. X    }
  826. X    return;
  827. X}
  828. X
  829. X/****************************************************************************
  830. X*    octal to integer                                                        *
  831. X****************************************************************************/
  832. X
  833. Xint    otoi (s)
  834. Xchar    *s;
  835. X{
  836. X    int        v, p, quit;
  837. X
  838. X    v = 0;
  839. X    while (*s == ' ')
  840. X        s++;
  841. X    quit = 0;
  842. X    while (*s)
  843. X    {    switch (*s)
  844. X        {
  845. X        case '0':    p = 0;  break;
  846. X        case '1':    p = 1;  break;
  847. X        case '2':    p = 2;  break;
  848. X        case '3':    p = 3;  break;
  849. X        case '4':    p = 4;  break;
  850. X        case '5':    p = 5;  break;
  851. X        case '6':    p = 6;  break;
  852. X        case '7':    p = 7;  break;
  853. X        default:    quit = 1;
  854. X        }
  855. X        if (quit)
  856. X            break;
  857. X        v = (v << 3) + p;
  858. X    }
  859. X    return (v);
  860. X}
  861. X
  862. X
  863. X/****************************************************************************
  864. X*    xlate_string ()                                                            *
  865. X*    translate the string according to the language translation vector        *
  866. X****************************************************************************/
  867. Xxlate_string (s)
  868. Xunsigned char    *s;
  869. X{
  870. X    int    sold;
  871. X    
  872. X    while (*s)
  873. X    {    sold = *s;
  874. X        *s = xlate[sold];
  875. X        s++;
  876. X    }
  877. X}
  878. X
  879. X
  880. X/****************************************************************************
  881. X*    usage()                                                                    *
  882. X****************************************************************************/
  883. Xusage ()
  884. X{
  885. X    fprintf (stderr, "Usage:  psfbanner Userid Name Requestid Printer Options Date\n");
  886. X    fprintf (stderr, "                   Machineid Title [-b n] [-g size] [-u f.def]\n");
  887. X    fprintf (stderr, "        where:   Userid, Name, etc are passed by lpsched\n");
  888. X    fprintf (stderr, "                 -b n    = select paper bin n\n");
  889. X    fprintf (stderr, "                 -g size = select paper size (letter, b5, etc)\n");
  890. X    fprintf (stderr, "                -u f.def = use this printer definition file\n");    
  891. X    exit (1);
  892. X}        
  893. END_OF_FILE
  894. if test 12737 -ne `wc -c <'psfbanner.c'`; then
  895.     echo shar: \"'psfbanner.c'\" unpacked with wrong size!
  896. fi
  897. # end of 'psfbanner.c'
  898. fi
  899. if test -f 'psfdoub.c' -a "${1}" != "-c" ; then 
  900.   echo shar: Will not clobber existing file \"'psfdoub.c'\"
  901. else
  902. echo shar: Extracting \"'psfdoub.c'\" \(17403 characters\)
  903. sed "s/^X//" >'psfdoub.c' <<'END_OF_FILE'
  904. X/* ta=4 */
  905. X
  906. X/****************************************************************************
  907. X*                p s f d o u b  . c                                            *
  908. X*                                                                            *
  909. X*    Filter a "single sided" document to become a "double sided document"    *
  910. X*                                                                            *
  911. X*    Tony Field.       tony@ajfcal.cuc.ab.ca                                    *
  912. X*                                                                            *
  913. X*    The basic algorithm for "print_book()"  was based on a routine written    *
  914. X*    by Tom Neff (tneff@well.uucp) named "book" which printed 5.5x8.5         *
  915. X*    double sided on an HP LaserJet.                                            *
  916. X****************************************************************************/
  917. X/*
  918. X * $Id: psfdoub.c,v 3.2 1992/01/19 05:50:33 ajf Exp ajf $
  919. X *
  920. X*/
  921. X/*    psfdoub prints simple reverse order or double sided.
  922. X
  923. X    if the printer is "Normal", i.e. stacks face down, then psf
  924. X    calls psfdoub to print simple reverse order or double sided.
  925. X    
  926. X    if the printer is  "Reverse", i.e. stacks face up, then psf
  927. X    calls psfdoub to print the file in reverse to make the page order
  928. X    as though it were "Normal".  It also calls psfdoub to print
  929. X    in book format. 
  930. X
  931. X    Separate page traversal strategies are needed for "Normal"
  932. X    and "Reverse" printers because of the different stacking methods.
  933. X    
  934. X    psfdoub will NOT print reversed order books or double sided!
  935. X    All book and double sided output is in normal order as
  936. X    far as the user is concerned.
  937. X
  938. X    Double sided print requires two scans over the data. The first scan
  939. X    by "psf" generates postscript output in normal (non-double sided)
  940. X    form. A second scan examines the postscript and re-orders the output
  941. X    to the printer. The second pass is always done by the "psfdoub" filter.
  942. X
  943. X    Psf generates extra information to make it easy for psfdoub to work.
  944. X    It simply constructs pointers to each of the %%Page: beginning
  945. X    in the print file.  (see function terminate_printer())  psfdoub
  946. X    uses the pointers to "skip about" the file while it does the
  947. X    actual page layout.
  948. X    
  949. X    If the target printer has two paper hoppers (i.e. #define HOPPER is
  950. X    defined and "nslots > 2") then psf creates a temp file and system("psfdoub
  951. X    fname") is called to immediately generate the double sided output.
  952. X    The user does not have to manually invoke psfdoub.
  953. X
  954. X    If HOPPER is not defined or nslots <= 1, psf simply creates an
  955. X    appropriate output file and the user must manually invoke psfdoub to
  956. X    print the file.
  957. X
  958. X    Double sided print is forced into this routine. It would have been
  959. X    simple except for the fact that 2-up "book" format is supported.
  960. X    The excuse for this strategy is, of course, to minimize the amount
  961. X    of file processing overhead when double sided printing is done.
  962. X    
  963. X    If the double sided printing is for 8.5x5.5 inch paper printed
  964. X    two-up, then psf carefully forgets (in function set_frame())
  965. X    to put in page scale, rotation, and translation information.  
  966. X    The psfdoub filter reads the page layout and carefully re-inserts 
  967. X    these when appropriate.  If 2-up "books" are made, each logical
  968. X    page becomes a separate page on the output temp file.
  969. X    the psf-generated control information is assumed to be at the
  970. X    end of the postscript print file.  The postscript file must contain
  971. X    a line like:
  972. X                    %PsfPtr: 21118
  973. X                    
  974. X    If the %PsPtr line is missing, then the file is NOT a book format.
  975. X    The format of this information is described in function read_control().
  976. X                
  977. X    psfdoub does little to normal double sided print other than to change
  978. X    the order in which the pages are printed.  It also adjusts the
  979. X    %%Pages: value to reflect the actual page count printed.
  980. X    
  981. X    psfdoub re-inserts translation, rotation and scale information eliminated
  982. X    by psf if the double sided print is to make an 8.5x5.5 "book".
  983. X
  984. X    Of course, a bunch of "very ugly" logic is needed for the "book"
  985. X    format to re-insert the postscript for page control - but it does work...
  986. X*/
  987. X
  988. X#include <stdio.h>
  989. X#include <string.h>
  990. X#include <signal.h>
  991. X#include <malloc.h>
  992. X#include <ctype.h>
  993. X#include "psf.h"
  994. X
  995. X/*    If books are made by generating two print files with the -s side count
  996. X    then set SIDECOUNT = 0  (i.e. no alternate paper hopper is available.
  997. X    
  998. X    If books are made by switching to the alternate print hopper for
  999. X    the second side, then set SIDECOUNT = 3  (i.e. second hopper is available
  1000. X    
  1001. X    Leave this set to 0.
  1002. X*/
  1003. X
  1004. X#define    SIDECOUNT    0
  1005. X
  1006. Xstatic int nsheets, nhalves;
  1007. Xstatic int row;
  1008. Xstatic int lpage, rpage;
  1009. Xvoid catch();
  1010. Xvoid trim();
  1011. X
  1012. Xchar    slots[NSLOTS][200] = 
  1013. X{            "statusdict begin 1 setpapertray end",
  1014. X            "statusdict begin 2 setpapertray end",
  1015. X            "", "", "", ""
  1016. X} ;
  1017. Xint        nslots = 2;
  1018. X
  1019. Xchar    order_default[20] = "Normal";
  1020. Xchar    order_normal[100] = "\0";
  1021. Xchar    order_reverse[100] = "\0";
  1022. Xchar    *order_command = NULL;
  1023. X
  1024. X
  1025. Xchar    line[LONG_STR + 1];
  1026. Xchar    scale[100];
  1027. Xint        max_frame;
  1028. Xint        landscape;
  1029. Xint        real_width;
  1030. Xint        height;
  1031. Xint        width;
  1032. Xint     dx_home[4];
  1033. Xint     dy_home[4];
  1034. Xint        npage;
  1035. Xlong    *pg_loc;
  1036. Xlong    trailer_loc;
  1037. Xint        phys_page;
  1038. Xint        side;
  1039. Xint        bookwork;
  1040. Xint        alternate_tray = 0;
  1041. Xint        second_side = 0;
  1042. Xint        reverse_requested;        /*    user requested reverse?            */
  1043. Xint        reverse_order;            /*    actually reverse the sequence?    */
  1044. Xint        need_showpage = 0;        /*    is pending show page needed?     */
  1045. X
  1046. XFILE    *input_fp;
  1047. XFILE    *output_fp;
  1048. X
  1049. Xchar    *pgmname;
  1050. Xchar    *defref;
  1051. X
  1052. Xmain(argc, argv)
  1053. Xint        argc;
  1054. Xchar    *argv[];
  1055. X{    int        c, i, j;
  1056. X    extern char *optarg;
  1057. X    extern int    optind;
  1058. X    FILE    *pdef;
  1059. X    char    *env_fname;            /*    environment specified output file */
  1060. X    char    *getenv();
  1061. X    char    in_fname[100];
  1062. X    
  1063. X    /*    user may specify def file with -u */
  1064. X
  1065. X    reverse_requested = 0;
  1066. X    for (i = 0;  i < argc;  i++)
  1067. X    {
  1068. X        if (strncmp (argv[i], "-u", 2) == 0)
  1069. X        {    if (strlen (argv[i]) > 2)
  1070. X                defref = argv[i] + 2;
  1071. X            else
  1072. X                defref = argv[i+1];
  1073. X            break;
  1074. X        }
  1075. X    }
  1076. X    if (i >= argc)
  1077. X    {    if ((defref = getenv ("PSFDEF")) == NULL)
  1078. X            defref = PDEF;
  1079. X    }
  1080. X
  1081. X    if ((pdef = fopen (defref, "r")) != NULL)
  1082. X    {    char    line_type[200];
  1083. X        int        number;
  1084. X    
  1085. X        while (fgets (line, 200, pdef))
  1086. X        {    if (strncmp (line, "*printer", 8) == 0)
  1087. X                break;
  1088. X        }
  1089. X        nslots = 0;
  1090. X        fgets (line, 200, pdef);        /*    skip printer name     */
  1091. X
  1092. X        while (fgets (line, 200, pdef))
  1093. X        {    trim (line);
  1094. X            sscanf (line, "%s%d", line_type, &number);
  1095. X
  1096. X            if (strcmp (line_type, "*order") == 0)
  1097. X            {    fgets (line, 200, pdef);
  1098. X                line[19] = 0;
  1099. X                trim (line);
  1100. X                strcpy (order_default, line);
  1101. X                if (number > 1)
  1102. X                {    if (fgets (line, 200, pdef) == NULL)
  1103. X                        bad_file();
  1104. X                    trim (line);
  1105. X                    line[99] = 0;
  1106. X                    strcpy (order_normal, line);
  1107. X                    if (fgets (line, 200, pdef) == NULL)
  1108. X                        bad_file();
  1109. X                    trim (line);
  1110. X                    line[99] = 0;
  1111. X                    strcpy (order_reverse, line);
  1112. X                }
  1113. X            }
  1114. X
  1115. X            else if (strcmp (line_type, "*slots") == 0)
  1116. X            {    for (j = 0;  j < NSLOTS;  j++)
  1117. X                    slots[j][0] = 0;
  1118. X                for (i = j = 0;  i < number;  i++)
  1119. X                {    if (fgets (line, 200, pdef) == NULL)
  1120. X                        bad_file();
  1121. X                    if (i >= NSLOTS)
  1122. X                        continue;
  1123. X                    line[99] = 0;
  1124. X                    trim (line);
  1125. X                    strcpy (slots[i], line);
  1126. X                    j = i;
  1127. X                }
  1128. X                nslots = j + 1;
  1129. X            }
  1130. X
  1131. X            else if (strcmp (line_type, "*eof") == 0)
  1132. X                break;
  1133. X        }
  1134. X        fclose (pdef);
  1135. X    }
  1136. X
  1137. X    pgmname = argv[0];
  1138. X    if (argc == 1  ||  strcmp (argv[1], "-") == 0)
  1139. X        usage ();
  1140. X
  1141. X    side = SIDECOUNT;            /* print size 1, 2, or both = 3 */
  1142. X
  1143. X    while ((c = getopt(argc, argv, "123vu:-")) != -1)
  1144. X    {    switch (c)
  1145. X        {
  1146. X        case '1':
  1147. X        case '2':
  1148. X        case '3':
  1149. X            side = c - '0';
  1150. X            break;
  1151. X        case 'v':
  1152. X            reverse_requested = 1;
  1153. X            break;
  1154. X        case 'u':        /* alread processed */
  1155. X            break;
  1156. X        default:
  1157. X            usage ();
  1158. X        }
  1159. X    }
  1160. X    if (strcmp (order_default, "Reverse") == 0)
  1161. X    {    reverse_order = 1;
  1162. X    }
  1163. X    else
  1164. X        reverse_order = 0;
  1165. X    if (reverse_requested)
  1166. X        reverse_order = !reverse_order;
  1167. X    if (reverse_order  &&  order_reverse[0])
  1168. X        order_command = order_reverse;
  1169. X    else if (reverse_order == 0  &&  order_normal[0])
  1170. X        order_command = order_normal;
  1171. X    else
  1172. X        order_command = NULL;
  1173. X
  1174. X    if (reverse_requested  &&  side != 0)
  1175. X    {    fprintf (stderr, "Cannot print double sided or book in reverse order.\n");
  1176. X        exit (1);
  1177. X    }
  1178. X
  1179. X    if (side == 3  &&  nslots < 2)
  1180. X    {    fprintf (stderr, "Cannot use -3: only one output tray\n");
  1181. X        usage();
  1182. X    }
  1183. X
  1184. X    if ( side >= 4)
  1185. X    {    fprintf (stderr, "Print side must be 1, 2, or 3\n");
  1186. X        usage ();
  1187. X    }
  1188. X
  1189. X    if (optind >= argc)
  1190. X        strcpy (in_fname, BOOKFILE);
  1191. X    else
  1192. X        strcpy (in_fname, argv[optind]);
  1193. X
  1194. X    if (env_fname = getenv ("PSFLP"))
  1195. X#if defined(MSDOS)  ||  defined (__MSDOS__)
  1196. X    {    if ((output_fp = fopen (env_fname, "wt")) == NULL)
  1197. X#else
  1198. X    {    if ((output_fp = fopen (env_fname, "w")) == NULL)
  1199. X#endif
  1200. X        {    fprintf (stderr, "Cannot open output file %s\n", env_fname);
  1201. X            exit (1);
  1202. X        }
  1203. X    }
  1204. X    else
  1205. X        output_fp = stdout;
  1206. X
  1207. X    if ((pg_loc = (long *) malloc (sizeof (long) * MAX_PAGES)) == NULL)
  1208. X    {    fprintf (stderr, "%s: cannot allocate enough memory\n", pgmname);
  1209. X        exit (1);
  1210. X    }
  1211. X    
  1212. X    if ((input_fp = fopen(in_fname, "r")) == NULL)
  1213. X    {
  1214. X        fprintf(stderr, "%s: Error opening %s!\n", pgmname, in_fname);
  1215. X        exit (1);
  1216. X    }
  1217. X    (void)    signal (SIGINT, catch);        /*    for lpd quit */
  1218. X    read_control (input_fp);
  1219. X    get_prologue ();
  1220. X    if (reverse_order  &&  side == 0)
  1221. X        reverse_pages ();
  1222. X    else if (bookwork)
  1223. X        print_book ();
  1224. X    else
  1225. X        print_double ();
  1226. X    get_trailer ();
  1227. X    exit (0);
  1228. X}
  1229. X
  1230. X/****************************************************************************
  1231. X*    read_control()                                                            *
  1232. X*    Read the control information at the end of the file for the page         *
  1233. X*    dimensions and byte address of the start of each page.                    *
  1234. X*    Each of the parameter lines is a comment with the form %Psfxxxx: yyyy    *
  1235. X****************************************************************************/
  1236. X
  1237. Xread_control (fp)
  1238. XFILE    *fp;
  1239. X{    char    tail[100];
  1240. X    int        i, j;
  1241. X    long    atol(), psfloc;
  1242. X    
  1243. X    /*    %PsfPtr: xxx  --> xxx is the pointer to the first %Psf... line
  1244. X        in the file.  Seek to the indicated byte position to begin
  1245. X        reading the Psf generated information which looks like:
  1246. X
  1247. X                %%Trailer                            <--- (a)
  1248. X                %%DocumentFonts: Courier
  1249. X                %%Pages: 8
  1250. X                %PsfScale: 0.63194 0.79558 scale    <--- (b)
  1251. X                %PsfMargin: 2 1 612 769 626
  1252. X                %PsfHome: 0 0 0
  1253. X                %PsfHome: 1 626 0
  1254. X                %PsfHome: 2 0 0
  1255. X                %PsfHome: 3 0 0
  1256. X                %PsfPg: 0 405            <--- byte offsets to page
  1257. X                %PsfPg: 1 3885
  1258. X                %PsfPg: 2 7023
  1259. X                    ...
  1260. X                %PsfPg: 9999 21072        <--- points to (a) above
  1261. X                %PsfPtr: 21118            <--- points to (b) above
  1262. X                <ctrl/d>
  1263. X    */
  1264. X    fseek (fp, -50L, 2);
  1265. X    fread (tail, 50, 1, fp);
  1266. X    if ((i = tscan (tail, "%PsfPtr:")) == -1)
  1267. X    {    fprintf (stderr, "%s: File is not in psf book format\n", pgmname);
  1268. X        exit (1);
  1269. X    }
  1270. X    psfloc = atol (tail + i + 9);        /*    beginning  of psf information */
  1271. X    fseek (fp, psfloc, 0);
  1272. X    
  1273. X    fgets (scale, 99, fp);
  1274. X    strcpy (tail, scale + 11);            /* get rid of the %psf comment */
  1275. X    strcpy (scale, tail);
  1276. X
  1277. X    /*    fetch psf data.    */
  1278. X                                                        /*    %PsfMargin:    */
  1279. X    fscanf (fp, "%s %d %d %d %d %d", tail,
  1280. X                &max_frame, &landscape, &real_width, &height, &width);
  1281. X
  1282. X    bookwork = (max_frame == 2  &&  landscape && !reverse_requested);
  1283. X    for (i = 0;  i < 4;  i++)                            /*    %PsfHome:    */
  1284. X        fscanf (fp, "%s %d %d %d",  tail, &j, &dx_home[i], &dy_home[i]);
  1285. X
  1286. X    npage = 0;                                            /*    %PsfPg:        */
  1287. X    while (fscanf (fp, "%s %d %ld", tail, &i, &pg_loc[npage]) == 3)
  1288. X    {
  1289. X        if (i == 9999)
  1290. X        {    trailer_loc = pg_loc[npage];
  1291. X            break;
  1292. X        }
  1293. X        npage++;
  1294. X    }
  1295. X    fseek (fp, 0L, 0);
  1296. X}
  1297. X
  1298. X/****************************************************************************
  1299. X*    get_prologue()                                                            *
  1300. X*    Read the prologue and pass it directly to the output                    *
  1301. X****************************************************************************/
  1302. X
  1303. Xget_prologue ()
  1304. X{
  1305. X    fgets (line, LONG_STR, input_fp);        /*    skip the psf header     */
  1306. X    fprintf (output_fp, "%%!PS-Adobe-\n");    /*    write a valid header    */
  1307. X    while (fgets (line, LONG_STR, input_fp) != NULL)
  1308. X    {    if (strncmp (line, "%%Page:", 7) == 0)
  1309. X            break;
  1310. X        fputs (line, output_fp);
  1311. X    }
  1312. X}
  1313. X
  1314. X/****************************************************************************
  1315. X*    get_trailer ()                                                            *
  1316. X*    Read the trailer and pass it to the output.  Modify the page count to    *
  1317. X*    reflect the number of physical pages printed.                            *
  1318. X*    Remove any reference to the %Psf... lines.                                *
  1319. X****************************************************************************/
  1320. X
  1321. Xget_trailer ()
  1322. X{
  1323. X    if (phys_page == 0  ||  (bookwork  &&  second_side))
  1324. X        fprintf (output_fp, "showpage pg restore\n");
  1325. X    if (alternate_tray == 2)
  1326. X        fprintf (output_fp, "%s\n", slots[0]);
  1327. X    fseek (input_fp, trailer_loc, 0);
  1328. X    while (fgets (line, LONG_STR, input_fp) != NULL)
  1329. X    {    if (strncmp (line, "%%Pages:", 8) == 0)
  1330. X            fprintf (output_fp, "%%%%Pages: %d\n", phys_page);
  1331. X        else if (strncmp (line, "%Psf", 4) != 0)
  1332. X            fputs (line, output_fp);
  1333. X    }
  1334. X}
  1335. X
  1336. X/****************************************************************************
  1337. X*    display_page()                                                            *
  1338. X*    Send all ouput that belongs to a specific page.  For 8.5x5.5 books,        *
  1339. X*    generate the scale, etc that was omitted by psf.  Also enable the        *
  1340. X*    alternate tray if it to be used.                                        *
  1341. X****************************************************************************/
  1342. X
  1343. Xdisplay_page  (pgno, n)
  1344. Xint pgno;
  1345. Xint    n;
  1346. X{
  1347. X    fseek (input_fp, pg_loc[pgno], 0);
  1348. X    fgets (line, LONG_STR, input_fp);
  1349. X    if (n == 0)
  1350. X    {
  1351. X        if ((phys_page  &&  bookwork)  ||  need_showpage)
  1352. X            fprintf (output_fp, "showpage pg restore\n");
  1353. X
  1354. X        if (alternate_tray == 1)
  1355. X        {    alternate_tray = 2;
  1356. X            fprintf (output_fp, "%s\n", slots[1]);
  1357. X        }
  1358. X        fprintf (output_fp, "%%%%Page: ? %d\n", ++phys_page);
  1359. X
  1360. X        if ((bookwork  &&  max_frame == 2)  ||  pgno >= npage)
  1361. X        {    fprintf (output_fp, "/pg save def\n");
  1362. X        }
  1363. X        need_showpage = pgno >= npage;
  1364. X    }
  1365. X
  1366. X    if (bookwork)
  1367. X    {    if (n == 0)
  1368. X        {
  1369. X            fprintf (output_fp, "90 rotate 0 %d translate\n", -real_width);
  1370. X            fprintf (output_fp, "%s", scale);
  1371. X        }
  1372. X        fprintf (output_fp, "%d %d translate\n", dx_home[n], dy_home[n]);
  1373. X    }
  1374. X
  1375. X    if (pgno < npage)
  1376. X    {    while (fgets (line, LONG_STR, input_fp) != NULL)
  1377. X        {    if(strncmp (line, "%%", 2) == 0)
  1378. X                break;
  1379. X            fputs (line, output_fp);
  1380. X        }
  1381. X    }
  1382. X}
  1383. X
  1384. X
  1385. X/****************************************************************************
  1386. X*    print_book()                                                            *
  1387. X*    print_book() is based on Tom Neff's (tneff@well.uucp) "book"             *
  1388. X*    for the HP LaserJet                                                     *
  1389. X*    Scan the text to ensure that the 8.5x.5.5 pages are constructed in        *
  1390. X*    such a way that a "book" is generated - simply staple in the middle    .    *
  1391. X****************************************************************************/
  1392. X
  1393. Xprint_book ()        
  1394. X{    int    done;
  1395. X
  1396. X    nsheets = (npage+3)/4;
  1397. X    nhalves = nsheets*4;
  1398. X    phys_page = 0;
  1399. X
  1400. X    if (side == 1 ||  side == 3)
  1401. X    {    for (rpage=0, lpage=nhalves-1;  rpage < lpage;  rpage+=2, lpage-=2)
  1402. X        {
  1403. X            display_page (lpage, 0);
  1404. X            display_page (rpage, 1);
  1405. X        }
  1406. X    }
  1407. X
  1408. X    if (side == 3)
  1409. X        alternate_tray = 1;
  1410. X
  1411. X    if ((side == 2  ||  side == 3)  &&  nhalves > 1)
  1412. X    {    second_side = 1;
  1413. X        if (reverse_order)
  1414. X        {    /* printer stacks face up */
  1415. X            for (rpage=nhalves-2, lpage=1;  lpage < nhalves/2;  
  1416. X                        rpage-=2, lpage+=2)
  1417. X            {
  1418. X                display_page (lpage, 0);
  1419. X                display_page (rpage, 1);
  1420. X            }
  1421. X        }
  1422. X        else
  1423. X        {    /*    printer stacks face down */
  1424. X            for (rpage=nhalves/2, lpage=rpage-1; lpage >= 0; 
  1425. X                        rpage+=2, lpage-=2)
  1426. X            {
  1427. X                display_page (lpage, 0);
  1428. X                display_page (rpage, 1);
  1429. X            }
  1430. X        }
  1431. X    }
  1432. X    if (need_showpage)
  1433. X        fprintf (output_fp, "showpage pg restore\n");
  1434. X}
  1435. X
  1436. X/****************************************************************************
  1437. X*    print double()                                                            *
  1438. X*    print double sided pages.  first odd numbered, then even numbered.        *
  1439. X****************************************************************************/
  1440. X
  1441. Xprint_double ()
  1442. X{    int    apage;
  1443. X
  1444. X    nsheets = (npage+1)/2;
  1445. X    phys_page = 0;
  1446. X
  1447. X    if (side == 1  ||  side == 3)
  1448. X    {    for (apage = 0;  apage < nsheets;  apage++)
  1449. X        {    display_page (apage * 2, 0);
  1450. X        }
  1451. X    }
  1452. X
  1453. X    if (side == 3)
  1454. X        alternate_tray = 1;
  1455. X
  1456. X    if ((side == 2  ||  side == 3)  &&  npage > 1)
  1457. X    {    second_side = 1;
  1458. X        if (reverse_order)
  1459. X        {    /*    printer stacks face up */
  1460. X            for (apage = 0;  apage < nsheets;  apage++)
  1461. X            {    display_page (apage * 2 + 1, 0);
  1462. X            }
  1463. X        }
  1464. X        else
  1465. X        {    /* printer stacks face down */
  1466. X            for (apage = nsheets - 1;  apage >= 0;  apage--)
  1467. X            {    display_page (apage * 2 + 1, 0);
  1468. X            }
  1469. X        }
  1470. X        
  1471. X    }
  1472. X    if (need_showpage)
  1473. X        fprintf (output_fp, "showpage pg restore\n");
  1474. X}
  1475. X
  1476. X
  1477. X/****************************************************************************
  1478. X*    reverse_pages ()                                                        *
  1479. X*    normal print, reverse order of pages.                                    *
  1480. X****************************************************************************/
  1481. X
  1482. Xreverse_pages ()
  1483. X{
  1484. X    int pgno;
  1485. X
  1486. X    phys_page = 0;
  1487. X    for (pgno = npage-1;  pgno >= 0;  pgno--)
  1488. X        display_page (pgno, 0);
  1489. X}
  1490. X
  1491. X
  1492. Xtscan (s, t)        /* search for string t in s */
  1493. Xchar     s[], t[];
  1494. X{
  1495. X    int    i, j, k;
  1496. X    for (i = 0;  s[i] != '\0';  i++)
  1497. X    {    for (j = i, k=0;  t[k] != '\0'  &&  s[j] == t[k];  j++, k++)
  1498. X            ;
  1499. X        if (t[k] == '\0')
  1500. X            return (i);
  1501. X    }
  1502. X    return (-1);
  1503. X}
  1504. Xusage ()
  1505. X{
  1506. X    printf ("Usage:  psfdoub -n [-v] [-u f.def] file\n");
  1507. X    printf ("  where:         n = side number to print\n");
  1508. X    printf ("                -0 = not double sided (reverse print only)\n");
  1509. X    printf ("                -1 = print side 1 only\n");
  1510. X    printf ("                -2 = print side 2 only\n");
  1511. X    printf ("                -3 = print both sides in one pass\n");
  1512. X    printf ("                -v = reverse page order\n");
  1513. X    printf ("          -u f.def = use this .def file\n");
  1514. X    printf ("              file = print this file\n");
  1515. X    exit (0);
  1516. X}
  1517. X
  1518. Xvoid trim (s)                    /*    trim trailing blanks  and \n */
  1519. Xchar    *s;
  1520. X{    int many;
  1521. X
  1522. X    for (many = strlen (s) - 1;  many >= 0;  many--)
  1523. X    {    if (isgraph (s[many]))
  1524. X            break;
  1525. X        else
  1526. X            s[many] = '\0';
  1527. X    }
  1528. X}
  1529. X
  1530. X
  1531. X/********************************************************
  1532. X*    catch ()                                            *
  1533. X*    Catch SIGINT from lpd                                *
  1534. X********************************************************/
  1535. X
  1536. Xvoid catch (signo)
  1537. Xint    signo;
  1538. X{
  1539. X        fprintf (output_fp, "%c", 0x04);
  1540. X        exit (0);
  1541. X}
  1542. Xbad_file()
  1543. X{
  1544. X    fprintf (stderr, "Bad %s file\n", defref);
  1545. X    exit (1);
  1546. X}
  1547. X
  1548. END_OF_FILE
  1549. if test 17403 -ne `wc -c <'psfdoub.c'`; then
  1550.     echo shar: \"'psfdoub.c'\" unpacked with wrong size!
  1551. fi
  1552. # end of 'psfdoub.c'
  1553. fi
  1554. echo shar: End of archive 7 \(of 9\).
  1555. cp /dev/null ark7isdone
  1556. MISSING=""
  1557. for I in 1 2 3 4 5 6 7 8 9 ; do
  1558.     if test ! -f ark${I}isdone ; then
  1559.     MISSING="${MISSING} ${I}"
  1560.     fi
  1561. done
  1562. if test "${MISSING}" = "" ; then
  1563.     echo You have unpacked all 9 archives.
  1564.     rm -f ark[1-9]isdone ark[1-9][0-9]isdone
  1565. else
  1566.     echo You still need to unpack the following archives:
  1567.     echo "        " ${MISSING}
  1568. fi
  1569. ##  End of shell archive.
  1570. exit 0
  1571.  
  1572. exit 0 # Just in case...
  1573.